package com.hundsun.documentripper.service.impl;

import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hundsun.documentripper.domain.pojo.DocumentVersion;
import com.hundsun.documentripper.domain.pojo.File;
import com.hundsun.documentripper.domain.pojo.FileHistory;
import com.hundsun.documentripper.domain.pojo.FileNode;
import com.hundsun.documentripper.domain.pojo.FileNodeHistory;
import com.hundsun.documentripper.domain.query.FileQuery;
import com.hundsun.documentripper.error.BaseException;
import com.hundsun.documentripper.mapper.FileHistoryMapper;
import com.hundsun.documentripper.mapper.FileMapper;
import com.hundsun.documentripper.mapper.FileNodeHistoryMapper;
import com.hundsun.documentripper.mapper.FileNodeMapper;
import com.hundsun.documentripper.service.DocumentService;
import com.hundsun.documentripper.service.FileNodeService;
import com.hundsun.documentripper.service.FileService;
import com.hundsun.documentripper.service.ProductVersionService;

/**
 * Note：
 *
 * @author ：mengjw
 * @description：文件接口实现
 * @date ：Created in 2021/1/27
 */
@Service
public class FileServiceImpl implements FileService {

    @Autowired
    private DocumentService documentService;
    @Autowired
    private FileMapper fileMapper;
    @Autowired
    private FileHistoryMapper fileHistoryMapper;
    @Autowired
    private FileNodeMapper fileNodeMapper;
    @Autowired
    private FileNodeHistoryMapper fileNodeHistoryMapper;
    @Autowired
    private FileNodeService fileNodeService;
    @Autowired
    private ProductVersionService productVersionService;

    @Override
    public File insertFile(File file) {
        file.setUuid(UUID.randomUUID().toString());
        file.setDocumentUuid(UUID.randomUUID().toString());
        file.setDocumentVersion(0);
        // 插入文档数据
        documentService.insertDocumentFromFile(file);
        // 插入初始文件数据
        if (productVersionService.isLastProductVersion(file.getProductVersionUuid())) {
            fileMapper.insert(file);
        } else {
            fileHistoryMapper.insert(FileHistory.formFile(file));
        }
        return file;
    }

    @Override
    public void updateFile(File file) {
        // 可以更新对应版本的名字和上级uuid，不会额外创建文件
        File example = fileMapper.selectById(file.getUuid());
        if (null != example) {
            fileMapper.updateById(file);
        } else {
            fileHistoryMapper.updateById(FileHistory.formFile(file));
        }
    }

    @Override
    public File getFileById(String uuid) {
        File file = fileMapper.selectById(uuid);
        if (null == file) {
            file = fileHistoryMapper.selectById(uuid);
        }
        return file;
    }

    @Override
    public void deleteFile(String uuid) {
        File file = fileMapper.selectById(uuid);
        if (null != file) {
            // 判断是不是文件夹
            if (hasChild(file.getUuid(), false)) {
                throw new BaseException("4011");
            }
            // 如果不是空，不是历史数据
            fileMapper.deleteById(uuid);
            // 删除文件节点
            fileNodeService.deleteFileNodeById(uuid);
        } else {
            // 历史数据
            file = fileHistoryMapper.selectById(uuid);
            // 判断是不是文件夹
            if (hasChild(file.getUuid(), true)) {
                throw new BaseException("4011");
            }
            fileHistoryMapper.deleteById(uuid);
            fileNodeService.deleteFileNodeHistoryById(uuid);
        }
        // 删除相关的文档版本记录
        documentService.deleteDocumentVersionByFile(uuid);
    }

    @Override
    public List getFileListByVersion(String productVersionUuid) {
        if (productVersionService.isLastProductVersion(productVersionUuid)) {
            // 如果是最新的版本，从file表读取
            QueryWrapper<File> wrapper = new QueryWrapper<>();
            wrapper.eq("product_version_uuid", productVersionUuid);
            return fileMapper.selectList(wrapper);
        } else {
            // 如果是历史版本，读取历史表的同一个文档版本号最大的
            List<DocumentVersion> documentVersionList = documentService.getLastDocumentVersionByProductVersion(productVersionUuid);
            QueryWrapper<FileHistory> wrapper = new QueryWrapper<>();
            wrapper.eq("product_version_uuid", productVersionUuid);
            wrapper.in("uuid", documentVersionList.stream().map(DocumentVersion::getFileUuid).collect(Collectors.toList()));
            return fileHistoryMapper.selectList(wrapper);
        }
    }

    @Override
    public IPage getFileListByVersionByPage(FileQuery fileQuery) {
        String productVersionUuid = fileQuery.getProductVersionUuid();
        if (productVersionService.isLastProductVersion(productVersionUuid)) {
            // 如果是最新的版本，从file表读取
            QueryWrapper<File> wrapper = new QueryWrapper<>();
            wrapper.eq("product_version_uuid", productVersionUuid);
            wrapper.eq("is_folder", fileQuery.getIsFolder() == null ? false : fileQuery.getIsFolder());
            wrapper.orderByAsc("name");
            return fileMapper.selectPage(new Page<File>(fileQuery.getCurrent(), fileQuery.getSize()), wrapper);
        } else {
            // 如果是历史版本，读取历史表的同一个文档版本号最大的
            List<DocumentVersion> documentVersionList = documentService.getLastDocumentVersionByProductVersion(productVersionUuid);
            QueryWrapper<FileHistory> wrapper = new QueryWrapper<>();
            wrapper.eq("product_version_uuid", productVersionUuid);
            wrapper.eq("is_folder", fileQuery.getIsFolder() == null ? false : fileQuery.getIsFolder());
            wrapper.in("uuid", documentVersionList.stream().map(DocumentVersion::getFileUuid).collect(Collectors.toList()));
            wrapper.orderByAsc("name");
            return fileHistoryMapper.selectPage(new Page<FileHistory>(fileQuery.getCurrent(), fileQuery.getSize()), wrapper);
        }
    }

    @Override
    public void backupFile(String uuid) {
        // 归档到历史表
        fileHistoryMapper.insertFromFile(uuid);
        fileNodeHistoryMapper.insertFromFile(uuid);
        // 删除老的文件
        fileMapper.deleteById(uuid);
        fileNodeService.deleteFileNodeById(uuid);
    }

    @Override
    public void recoverFile(String productVersionUuid) {
        // 恢复到流水表
        fileMapper.insertFromFileHistory(productVersionUuid);
        QueryWrapper<File> wrapper = new QueryWrapper<>();
        wrapper.eq("product_version_uuid", productVersionUuid);
        List<File> fileList = fileMapper.selectList(wrapper);
        for (File file : fileList) {
            fileNodeMapper.insertFromFileNodeHistory(file.getUuid());
        }
        // 删除历史文件
        deleteFileHistoryByVersion(productVersionUuid);
    }

    @Override
    public void newFile(File file) {
        // 将旧文件及其节点备份到历史表
        String oldFileUuid = file.getUuid();
        file.setUuid(UUID.randomUUID().toString());
        fileHistoryMapper.insertFromFile(oldFileUuid);
        fileNodeHistoryMapper.insertFromFile(oldFileUuid);
        // 删除旧文件和插入新文件
        fileMapper.deleteById(oldFileUuid);
        fileMapper.insert(file);
        fileNodeMapper.updateFileUuid(oldFileUuid, file.getUuid());
        // 插入新的文档版本信息
        DocumentVersion documentVersion = DocumentVersion.builder()
                .documentUuid(file.getDocumentUuid())
                .documentVersion(1)
                .productVersionUuid(file.getProductVersionUuid())
                .fileUuid(file.getUuid())
                .createUser(file.getCreateUser())
                .build();
        documentService.insertDocumentVersion(documentVersion);
    }

    @Override
    public void deleteFileByVersion(String productVersionUuid) {
        // 删除文件
        QueryWrapper<File> wrapper = new QueryWrapper<>();
        wrapper.eq("product_version_uuid", productVersionUuid);
        List<File> fileList = fileMapper.selectList(wrapper);
        fileMapper.delete(wrapper);
        // 根据文件的文件编号删除相关节点
        QueryWrapper<FileNode> nodeWrapper = new QueryWrapper<>();
        nodeWrapper.in("file_uuid", fileList.stream().map(File::getUuid).collect(Collectors.toList()));
        fileNodeMapper.delete(nodeWrapper);
    }

    @Override
    public void deleteFileHistoryByVersion(String productVersionUuid) {
        // 删除历史文件
        QueryWrapper<FileHistory> wrapper = new QueryWrapper<>();
        wrapper.eq("product_version_uuid", productVersionUuid);
        List<FileHistory> fileHistoryList = fileHistoryMapper.selectList(wrapper);
        fileHistoryMapper.delete(wrapper);
        // 根据历史文件的文件编号删除相关节点
        QueryWrapper<FileNodeHistory> nodeWrapper = new QueryWrapper<>();
        nodeWrapper.in("file_uuid", fileHistoryList.stream().map(FileHistory::getUuid).collect(Collectors.toList()));
        fileNodeHistoryMapper.delete(nodeWrapper);
    }

    @Override
    public Boolean hasChild(String parentUuid, Boolean isHistory) {
        if (isHistory) {
            QueryWrapper<FileHistory> wrapper = new QueryWrapper<>();
            wrapper.eq("parent_uuid", parentUuid);
            List<FileHistory> fileList = fileHistoryMapper.selectList(wrapper);
            return !fileList.isEmpty();
        } else {
            QueryWrapper<File> wrapper = new QueryWrapper<>();
            wrapper.eq("parent_uuid", parentUuid);
            List<File> fileList = fileMapper.selectList(wrapper);
            return !fileList.isEmpty();
        }
    }

}